﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Media;
using System;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Input;
using Fighter.GameContent;
using System.Threading;
using Fighter.ScreenManagers;
using System.IO;

namespace Fighter.Screens
{
    /// <summary>
    /// Menu pour gérer les différentes commandes du jeu
    /// </summary>
    class CommandsMenuScreen : MenuScreen
    {
        #region Fields

        MenuEntry jumpMenuEntry;
        MenuEntry upMenuEntry;
        MenuEntry downMenuEntry;
        MenuEntry rightMenuEntry;
        MenuEntry leftMenuEntry;
        MenuEntry fireMenuEntry;
        MenuEntry attackMenuEntry;

        #endregion

        #region Initialization


        /// <summary>
        /// Constructeur
        /// </summary>
        public CommandsMenuScreen()
            : base("Commandes")
        {
            // Création des entrées du menu
            jumpMenuEntry = new MenuEntry(string.Empty);
            upMenuEntry = new MenuEntry(string.Empty);
            downMenuEntry = new MenuEntry(string.Empty);
            rightMenuEntry = new MenuEntry(string.Empty);
            leftMenuEntry = new MenuEntry(string.Empty);
            fireMenuEntry = new MenuEntry(string.Empty);
            attackMenuEntry = new MenuEntry(string.Empty);

            SetJumpMenuEntryText();
            SetUpMenuEntryText();
            SetDownMenuEntryText();
            SetRightMenuEntryText();
            SetLeftMenuEntryText();
            SetFireMenuEntryText();
            SetAttackMenuEntryText();

            MenuEntry back = new MenuEntry("Retour");

            // Ajout des évènements
            back.Selected += OnCancel;

            // Ajout des entrées du menu
            MenuEntries.Add(jumpMenuEntry);
            MenuEntries.Add(upMenuEntry);
            MenuEntries.Add(downMenuEntry);
            MenuEntries.Add(rightMenuEntry);
            MenuEntries.Add(leftMenuEntry);
            MenuEntries.Add(fireMenuEntry);
            MenuEntries.Add(attackMenuEntry);
            MenuEntries.Add(back);
        }


        /// <summary>
        /// Remplit l'entrée "Saut" avec la touche associée
        /// </summary>
        void SetJumpMenuEntryText()
        {
            jumpMenuEntry.Text = "Saut : " + Config.Instance.Jump;
        }

        /// <summary>
        /// Remplit l'entrée "Haut" avec la touche associée
        /// </summary>
        void SetUpMenuEntryText()
        {
            upMenuEntry.Text = "Haut : " + Config.Instance.Up;
        }

        /// <summary>
        /// Remplit l'entrée "Bas" avec la touche associée
        /// </summary>
        void SetDownMenuEntryText()
        {
            downMenuEntry.Text = "Bas : " + Config.Instance.Down;
        }

        /// <summary>
        /// Remplit l'entrée "Droite" avec la touche associée
        /// </summary>
        void SetRightMenuEntryText()
        {
            rightMenuEntry.Text = "Droite : " + Config.Instance.Right;
        }

        /// <summary>
        /// Remplit l'entrée "Gauche" avec la touche associée
        /// </summary>
        void SetLeftMenuEntryText()
        {
            leftMenuEntry.Text = "Gauche : " + Config.Instance.Left;
        }

        /// <summary>
        /// Remplit l'entrée "Tirer" avec la touche associée
        /// </summary>
        void SetFireMenuEntryText()
        {
            fireMenuEntry.Text = "Tir : " + Config.Instance.Fire;
        }

        /// <summary>
        /// Remplit l'entrée "Attaque" avec la touche associée
        /// </summary>
        void SetAttackMenuEntryText()
        {
            attackMenuEntry.Text = "Attaque : " + Config.Instance.Attack;
        }

        #endregion

        #region Handle Input

        /// <summary>
        /// Surcharge de la méthode HandleInput pour permettre de gérer
        /// le changement d'affectation d'une touche
        /// </summary>
        public override void HandleInput(InputState input)
        {
            // Move to the previous menu entry?
            if (input.IsMenuUp(ControllingPlayer))
            {
                SelectedEntry--;

                if (SelectedEntry < 0)
                    SelectedEntry = MenuEntries.Count - 1;
            } 
            
            if (input.IsMenuDown(ControllingPlayer))
            {
                // Move to the next menu entry?
                SelectedEntry++;

                if (SelectedEntry >= MenuEntries.Count)
                    SelectedEntry = 0;
            }

            // Permet de gérer les différentes affectations de touches
            Keys[] keysPressed = Keyboard.GetState().GetPressedKeys();
            if (keysPressed.Length == 1 && keysPressed[0] != Keys.Up && keysPressed[0] != Keys.Down
                && keysPressed[0] != Keys.Left && keysPressed[0] != Keys.Right && keysPressed[0] != Keys.Escape 
                && keysPressed[0] != Keys.Enter)
            {
                Keys key = Keyboard.GetState().GetPressedKeys()[0];
                if (MenuEntries[SelectedEntry].Equals(jumpMenuEntry))
                {
                    Config.Instance.Jump = key;
                    SetJumpMenuEntryText();
                }

                if (MenuEntries[SelectedEntry].Equals(upMenuEntry))
                {
                    Config.Instance.Up = key;
                    SetUpMenuEntryText();
                }

                if (MenuEntries[SelectedEntry].Equals(downMenuEntry))
                {
                    Config.Instance.Down = key;
                    SetDownMenuEntryText();
                }

                if (MenuEntries[SelectedEntry].Equals(rightMenuEntry))
                {
                    Config.Instance.Right = key;
                    SetRightMenuEntryText();
                }

                if (MenuEntries[SelectedEntry].Equals(leftMenuEntry))
                {
                    Config.Instance.Left = key;
                    SetLeftMenuEntryText();
                }

                if (MenuEntries[SelectedEntry].Equals(fireMenuEntry))
                {
                    Config.Instance.Fire = key;
                    SetFireMenuEntryText();
                }

                if (MenuEntries[SelectedEntry].Equals(attackMenuEntry))
                {
                    Config.Instance.Attack = key;
                    SetAttackMenuEntryText();
                }
            }

            // Accept or cancel the menu? We pass in our ControllingPlayer, which may
            // either be null (to accept input from any player) or a specific index.
            // If we pass a null controlling player, the InputState helper returns to
            // us which player actually provided the input. We pass that through to
            // OnSelectEntry and OnCancel, so they can tell which player triggered them.
            PlayerIndex playerIndex;

            if (input.IsMenuSelect(ControllingPlayer, out playerIndex))
            {
                OnSelectEntry(SelectedEntry, playerIndex);
            }
            else if (input.IsMenuCancel(ControllingPlayer, out playerIndex))
            {
                OnCancel(playerIndex);
            }
        }

        /// <summary>
        /// Evènement lorsque l'option "Retour" a été choisie
        /// </summary>
        protected override void OnCancel(PlayerIndex playerIndex)
        {
            System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(typeof(Config));
            TextWriter tw = new StreamWriter("Content/Game/config.xml");
            x.Serialize(tw, Config.Instance);
            tw.Close();
            ExitScreen();
        }

        #endregion
    }
}
